Skip to content

fix(core): tolerate AlreadyExists in FSUtil.ensureDir#36542

Merged
rekram1-node merged 6 commits into
anomalyco:devfrom
BB-84C:ensuredir-alreadyexists
Jul 15, 2026
Merged

fix(core): tolerate AlreadyExists in FSUtil.ensureDir#36542
rekram1-node merged 6 commits into
anomalyco:devfrom
BB-84C:ensuredir-alreadyexists

Conversation

@BB-84C

@BB-84C BB-84C commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #35828

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

v1.17.15 added fs.ensureDir(dir) to Config.ensureGitignore, which runs for every resolved config directory during Config.loadInstanceState, and the call site is wrapped in Effect.orDie. FSUtil.ensureDir calls makeDirectory(path, { recursive: true }) with no error handling.

Recursive makeDirectory is supposed to be idempotent, but on some Windows runtimes it reports AlreadyExists for a directory that already exists. So once a project had a .opencode directory, startup died with "Unexpected server error" (works on 1.17.14, broke on 1.17.15).

The fix makes ensureDir treat AlreadyExists as success, but only when the path is actually a directory — a file sitting at that path still fails. This mirrors the NotFound catch already used a few lines down in writeWithDirs, so behavior only changes for the exact reported case.

How did you verify your code works?

  • Added a regression test that injects an AlreadyExists result from makeDirectory: it fails without this patch and passes with it.
  • Added a guard test asserting ensureDir still fails when a file occupies the path.
  • packages/core filesystem suite passes (29 tests) and bun typecheck for packages/core is clean.

I couldn't reproduce the crash on my own machine — recursive mkdir is idempotent on my Bun build — which is why the regression test injects the error directly instead of depending on the platform quirk.

Screenshots / recordings

N/A — not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Jul 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Recursive makeDirectory should be idempotent, but some Windows runtimes
surface AlreadyExists for a directory that already exists. Since v1.17.15,
Config.ensureGitignore calls fs.ensureDir on every resolved config
directory, so startup crashed with 'Unexpected server error' whenever a
project's .opencode directory already existed.

ensureDir now treats AlreadyExists as success when the path is already a
directory, while still failing when a file occupies the path.

Fixes anomalyco#35828
@rekram1-node

Copy link
Copy Markdown
Collaborator

apologies, playing around w/ ur pr

@BB-84C

BB-84C commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

apologies, playing around w/ ur pr

@rekram1-node No problem at all, thanks for your time with this PR!

@rekram1-node rekram1-node force-pushed the ensuredir-alreadyexists branch from c229056 to e82a069 Compare July 15, 2026 01:10
@rekram1-node

Copy link
Copy Markdown
Collaborator

Reduced this back to the minimum production fix and removed the added regression-test scaffolding. I am not retaining a native Windows regression test because the Windows CI probe passed with the workaround omitted, so that test did not reproduce or validate the reported failure. A synthetic filesystem that always returns AlreadyExists only proves the recovery branch itself, not the real Windows failure mode.

@rekram1-node rekram1-node merged commit 656f299 into anomalyco:dev Jul 15, 2026
8 checks passed
@BB-84C

BB-84C commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Reduced this back to the minimum production fix and removed the added regression-test scaffolding. I am not retaining a native Windows regression test because the Windows CI probe passed with the workaround omitted, so that test did not reproduce or validate the reported failure. A synthetic filesystem that always returns AlreadyExists only proves the recovery branch itself, not the real Windows failure mode.

@rekram1-node Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows TUI fails in v1.17.15 when project .opencode already exists

2 participants